home *** CD-ROM | disk | FTP | other *** search
- /*
- * initialization routines
- * this initializes various things used to verify the
- * validity of the password
- */
- #include "passwd.h"
-
- /*
- * this table contains all the information one could ever want to know
- * about the internal variables
- */
- struct intvar iv[] = {
- { 'A', TY_STR, CH_NULL, CH_NULL, 1, "user variable A [%s]: ", },
- { 'B', TY_STR, CH_NULL, CH_NULL, 1, "user variable B [%s]: ", },
- { 'C', TY_STR, CH_NULL, CH_NULL, 1, "user variable C [%s]: ", },
- { 'D', TY_STR, CH_NULL, CH_NULL, 1, "user variable D [%s]: ", },
- { 'E', TY_STR, CH_NULL, CH_NULL, 1, "user variable E [%s]: ", },
- { 'F', TY_STR, CH_NULL, CH_NULL, 1, "user variable F [%s]: ", },
- { 'G', TY_STR, CH_NULL, CH_NULL, 1, "user variable G [%s]: ", },
- { 'H', TY_STR, CH_NULL, CH_NULL, 1, "user variable H [%s]: ", },
- { 'I', TY_STR, CH_NULL, CH_NULL, 1, "user variable I [%s]: ", },
- { 'J', TY_STR, CH_NULL, CH_NULL, 1, "user variable J [%s]: ", },
- { 'K', TY_STR, CH_NULL, CH_NULL, 1, "user variable K [%s]: ", },
- { 'L', TY_STR, CH_NULL, CH_NULL, 1, "user variable L [%s]: ", },
- { 'M', TY_STR, CH_NULL, CH_NULL, 1, "user variable M [%s]: ", },
- { 'N', TY_STR, CH_NULL, CH_NULL, 1, "user variable N [%s]: ", },
- { 'O', TY_STR, CH_NULL, CH_NULL, 1, "user variable O [%s]: ", },
- { 'P', TY_STR, CH_NULL, CH_NULL, 1, "user variable P [%s]: ", },
- { 'Q', TY_STR, CH_NULL, CH_NULL, 1, "user variable Q [%s]: ", },
- { 'R', TY_STR, CH_NULL, CH_NULL, 1, "user variable R [%s]: ", },
- { 'S', TY_STR, CH_NULL, CH_NULL, 1, "user variable S [%s]: ", },
- { 'T', TY_STR, CH_NULL, CH_NULL, 1, "user variable T [%s]: ", },
- { 'U', TY_STR, CH_NULL, CH_NULL, 1, "user variable U [%s]: ", },
- { 'V', TY_STR, CH_NULL, CH_NULL, 1, "user variable V [%s]: ", },
- { 'W', TY_STR, CH_NULL, CH_NULL, 1, "user variable W [%s]: ", },
- { 'X', TY_STR, CH_NULL, CH_NULL, 1, "user variable X [%s]: ", },
- { 'Y', TY_STR, CH_NULL, CH_NULL, 1, "user variable Y [%s]: ", },
- { 'Z', TY_STR, CH_NULL, CH_NULL, 1, "user variable Z [%s]: ", },
- { 'a', TY_NUM, CH_NULL, CH_NULL, 0, CH_NULL, /* alphanumerics */ },
- { 'b', TY_NUM, CH_NULL, CH_NULL, 0, CH_NULL, /* alphabetics */ },
- { 'c', TY_NUM, CH_NULL, CH_NULL, 0, CH_NULL, /* capitals */ },
- { 'd', TY_STR, CH_NULL, CH_NULL, 0, CH_NULL, /* domain name */ },
- { 'f', TY_STR, CH_NULL, CH_NULL, 1, "First Name [%s]: ", },
- { 'g', TY_STR, CH_NULL, CH_NULL, 0, CH_NULL, /* group name */ },
- { 'h', TY_STR, CH_NULL, CH_NULL, 0, CH_NULL, /* host name */ },
- { 'i', TY_STR, CH_NULL, CH_NULL, 1, "Initials [%s]: ", },
- { 'l', TY_NUM, CH_NULL, CH_NULL, 0, CH_NULL, /* small letters */ },
- { 'm', TY_STR, CH_NULL, CH_NULL, 1, "Middle Name [%s]: ", },
- { 'n', TY_STR, CH_NULL, CH_NULL, 1, "Full Name [%s]: ", },
- { 'o', TY_STR, CH_NULL, CH_NULL, 1, "Office [%s]: ", },
- { 'p', TY_STR, CH_NULL, CH_NULL, 0, CH_NULL, /* new password */ },
- { 'q', TY_STR, CH_NULL, CH_NULL, 0, CH_NULL, /* old password */ },
- { 's', TY_STR, CH_NULL, CH_NULL, 1, "Last Name [%s]: ", },
- { 't', TY_STR, CH_NULL, CH_NULL, 1, "Phone Number [%s]: ", },
- { 'u', TY_STR, CH_NULL, CH_NULL, 0, CH_NULL, /* user name */ },
- { 'v', TY_NUM, CH_NULL, CH_NULL, 0, CH_NULL, /* mixed case */ },
- { 'w', TY_NUM, CH_NULL, CH_NULL, 0, CH_NULL, /* digits */ },
- { '\0',TY_NUM, CH_NULL, CH_NULL, 0, CH_NULL, /* END-OF-LIST */ },
- };
-
- /*
- * this initializes the variables associated with the password
- */
- initpw()
- {
- char buf[BUFSIZ]; /* buffer for string constants */
- register char *p; /* pointer in a for loop */
- struct group *g; /* points to user's group info */
- int len; /* length of password */
- int iupper; /* number of uppercase characters */
- int ilower; /* number of lowercase characters */
- int ialpha; /* number of alphabetic characters */
- int inum; /* number of numeric characters */
- int ialnum; /* number of alphanumeric characters */
-
- /*
- * assign the password, name, host, domain, etc.
- */
- if (pwsig > 0){
- (void) strncpy(buf, password, pwsig);
- buf[pwsig] = '\0';
- IVSASSIGN('p', buf);
- }
- else
- IVSASSIGN('p', password);
- if (pwsig > 0){
- (void) strncpy(buf, oldpassword, pwsig);
- buf[pwsig] = '\0';
- IVSASSIGN('q', buf);
- }
- else
- IVSASSIGN('q', oldpassword);
- IVSASSIGN('u', pwinfo->pw_name);
- if ((g = getgrgid(pwinfo->pw_gid)) == GR_NULL)
- IVSASSIGN('g', CH_NULL) /* no semicolon here! */
- else
- IVSASSIGN('g', g->gr_name);
- if (findhost(buf, BUFSIZ) < 0)
- IVSASSIGN('h', CH_NULL) /* no semicolon here! */
- else
- IVSASSIGN('h', buf);
- if (finddomain(buf, BUFSIZ) < 0)
- IVSASSIGN('d', CH_NULL) /* no semicolon here! */
- else
- IVSASSIGN('d', buf);
-
- /*
- * do some quick counts of characters
- * only the first pwsig characters count
- */
- len = iupper = ilower = ialpha = inum = ialnum = 0;
- for(p = findiv('p')->string; *p; p++){
- len++; /* one more to the length */
- if (isupper(*p)) /* upper case */
- iupper++;
- else if (islower(*p)) /* lower case */
- ilower++;
- if (isalpha(*p)){ /* alphabetic */
- ialpha++;
- ialnum++;
- }
- else if (isdigit(*p)){ /* numeric */
- inum++;
- ialnum++;
- }
- }
- IVNASSIGN('a', ialnum, len - ialnum);
- IVNASSIGN('b', ialpha, len - ialpha);
- IVNASSIGN('c', iupper, len - iupper);
- IVNASSIGN('l', ilower, len - ilower);
- IVNASSIGN('v', !(iupper && ilower), (iupper && ilower));
- IVNASSIGN('w', inum, len - inum);
- }
-
- /*
- * load the number of significant chars in the password
- */
- loadsig(number)
- char *number;
- {
- register int sgn; /* 1 if number is negative */
- char buf[BUFSIZ]; /* buffer for new password */
-
- /*
- * skip leading blanks
- */
- while(isspace(*number))
- number++;
- /*
- * grab the sign if any
- */
- sgn = 0;
- if (*number == '+' || *number == '-')
- sgn = (*number++ == '-');
- /*
- * if there's no number, ignore the line
- */
- if (!isdigit(*number))
- return;
- /*
- * read the number as the number of significant characters
- * and set the sign properly
- */
- pwsig = 0;
- while(isdigit(*number))
- pwsig = pwsig * 10 + *number++ - '0';
- if (sgn)
- pwsig = -pwsig;
- else if (pwsig >= BUFSIZ)
- pwsig = BUFSIZ-1;
- /*
- * now reset the password to be interpolated
- */
- if (pwsig > 0){
- (void) strncpy(buf, password, pwsig);
- buf[pwsig] = '\0';
- IVSASSIGN('p', buf);
- }
- else
- IVSASSIGN('p', password);
- LOG2(LG_DEBUG, "passwd: \"%s\",\"%s\"",
- findiv('p')->string, findiv('p')->length);
- }
-
- /*
- * load the escapes defined by the GECOS field
- */
- loadgecos(format, prfmt, list)
- char *format; /* what to analyze */
- char *prfmt; /* printf format string */
- char *list; /* how to parse it */
- {
- register char *f, *fb; /* used to collect the format string */
- char fbuf[BUFSIZ]; /* format string stuffed here */
- register int i; /* counter in a for loop */
- register int n; /* number of strings read in */
- char pbuf[2*BUFSIZ]; /* buffer for gecos field (no &s) */
- /* space for strings */
- char addr1[GECOSSIZE], addr2[GECOSSIZE], addr3[GECOSSIZE];
- char addr4[GECOSSIZE], addr5[GECOSSIZE], addr6[GECOSSIZE];
- char addr7[GECOSSIZE], addr8[GECOSSIZE], addr9[GECOSSIZE];
- char *addrs[9]; /* walks the above arrays */
- int ff = 0; /* 1 if first name read */
- int fm = 0; /* 1 if middle name read */
- int fl = 0; /* 1 if last name read */
- int fn = 0; /* 1 if full name read */
- int fi = 0; /* 1 if initials read */
- struct intvar *ip; /* points to internal variable */
-
- /*
- * initialize the reading areas
- */
- addrs[0] = addr1; addrs[1] = addr2; addrs[2] = addr3;
- addrs[3] = addr4; addrs[4] = addr5; addrs[5] = addr6;
- addrs[6] = addr7; addrs[7] = addr8; addrs[8] = addr9;
- /*
- * expand gecos field, replacing & by login name
- */
- fb = pbuf;
- for(f = pwinfo->pw_gecos; *f; f++)
- if (*f == '&'){
- if (pwinfo->pw_name != CH_NULL){
- register char *ob = pwinfo->pw_name;
- while(*ob)
- *fb++ = *ob++;
- }
- }
- else
- *fb++ = *f;
- *fb = '\0';
-
- /*
- * now read in the format string
- */
- for(f = format; *f && *f != '"'; f++);
- /*
- * none present -- skip line
- */
- if (!*f)
- return(-1);
- /*
- * skip initial quote, stuff string
- */
- if (prfmt == CH_NULL)
- fb = fbuf;
- else
- fb = prfmt;
- for(f++; *f && *f != '"'; *fb++ = *f++);
- *fb = '\0';
- /*
- * no closing quote -- ignore line
- */
- if (!*f){
- LOG1(LG_SYNTAX,
- "missing \" in GECOS specification on line %d", linect);
- return(-1);
- }
- /*
- * skip closing quote
- */
- f++;
-
- /*
- * read in the strings
- */
- n = sscanf(pbuf, (prfmt == CH_NULL) ? fbuf : prfmt,
- addr1, addr2, addr3, addr4, addr5,
- addr6, addr7, addr8, addr9);
- /*
- * quickly check the format of the symbols
- */
- fb = f;
- i = 0;
- while(*fb && (findiv(*fb) != IV_NULL || isspace(*fb))){
- if (!isspace(*fb))
- i++;
- fb++;
- }
- if (*fb && findiv(*fb) == IV_NULL){
- LOG2(LG_SYNTAX,
- "bad GECOS specification at line %d (\"%s\")",
- linect, fb);
- return(-1);
- }
- else if (i != n){
- LOG1(LG_SYNTAX,
- "wrong number of escapes in GECOS specification on line %d",
- linect);
- return(-1);
- }
-
- /*
- * process them
- */
- for(i = 0; i < n; i++){
- /*
- * skip white space
- */
- while(isspace(*f))
- f++;
- /*
- * next char says what it is
- */
- if (list != CH_NULL)
- *list++ = *f;
- if (*f == '\0' || *f == '\n')
- break;
- /*
- * make the assignment or report an error
- */
- ip = findiv(*f++);
- if (!ip->userset){
- LOG2(LG_SYNTAX,
- "bad GECOS specification at line %d (\"%s\")",
- linect, &f[-1]);
- break;
- }
- IVSPASSIGN(ip, addrs[i]);
- switch(ip->name){
- case 'f': ff++; break; /* first name */
- case 'm': fm++; break; /* middle name */
- case 's': fl++; break; /* last name */
- case 'i': fi++; break; /* initials */
- case 'n': fn++; break; /* full name */
- }
- }
- if (list != CH_NULL)
- *list = '\0';
-
- /*
- * if the full name is given derive the first, middle, and last
- */
- ip = findiv('n');
- if (fn && (f = index(ip->string, ',')) == NULL){
- /*
- * name is of the form "first middle last"
- * so get the last name first and stuff it in
- * addr1
- */
- f = ip->string;
- for(fb = addr1; isalpha(*f) || *f == '-'; *fb++ = *f++);
- *fb = '\0';
- /*
- * now go for the second name
- * skip leading white spaces
- */
- while(*f && !isalpha(*f))
- f++;
- if (*f){
- /*
- * if there is a second name, the first was
- * the first name; assign it
- */
- if (!ff)
- IVSASSIGN('s', addr2);
- /*
- * grab the second name
- */
- for(fb = addr2; isalpha(*f) || *f == '-'; *fb++ = *f++);
- *fb = '\0';
- /*
- * now go for the third name
- * skip leading white spaces
- */
- while(*f && !isalpha(*f))
- f++;
- if (*f){
- /*
- * grab the third name
- */
- for(fb = addr3; isalpha(*f) || *f == '-';
- *fb++ = *f++);
- *fb = '\0';
- /*
- * assign the middle and last names (phew!)
- */
- if (!fm)
- IVSASSIGN('m', addr2);
- if (!fl)
- IVSASSIGN('s', addr3);
- }
- /*
- * two names only; assign last name
- */
- else if (!fl)
- IVSASSIGN('s', addr2);
- }
- /*
- * one name only; assign as last name
- */
- else if (!fl)
- IVSASSIGN('s', addr1);
- }
- else if (fn){
- /*
- * name is of the form "last, first middle"
- * so get the last name first and stuff it in
- * addr1
- */
- f = ip->string;
- for(fb = addr1; isalpha(*f) || *f == '-'; *fb++ = *f++);
- *fb = '\0';
- /*
- * if last name not known, assign it
- */
- if (!fl)
- IVSASSIGN('s', addr1);
- /*
- * now go for the first and middle names
- * skip nonletters spaces
- */
- while(*f && !isalpha(*f))
- f++;
- if (*f){
- /*
- * get the next name and save it in addr1
- */
- for(fb = addr1; isalpha(*f) || *f == '-'; *fb++ = *f++);
- *fb = '\0';
- /*
- * if first name not known, you got it
- */
- if (!ff)
- IVSASSIGN('f', addr1);
- /*
- * now go for the middle name
- * skip nonletters spaces
- */
- while(*f && !isalpha(*f))
- f++;
- if (*f){
- /*
- * get the next name and save it in addr1
- */
- for(fb = addr1; isalpha(*f) || *f == '-';
- *fb++ = *f++);
- *fb = '\0';
- /*
- * if middle name not known, you got it
- */
- if (!fm)
- IVSASSIGN('m', addr1);
- }
- }
- /*
- * the name must now be rebuilt in the more usual form
- * "first middle last"; the next part does this, so we
- * force it to be taken by pretending we never saw the name
- */
- fn = 0;
- }
-
- /*
- * full name not yet known -- fill it in
- */
- if (!fn){
- /*
- * load into buffer one name at a time,
- * including spaces between the relevant names
- */
- fbuf[0] = '\0';
- ip = findiv('f');
- if (ip->string != CH_NULL)
- (void) strcat(fbuf, ip->string);
- ip = findiv('m');
- if (ip->string != CH_NULL){
- if (fbuf[0] != '\0')
- (void) strcat(fbuf, " ");
- (void) strcat(fbuf, ip->string);
- }
- ip = findiv('s');
- if (ip->string != CH_NULL){
- if (fbuf[0] != '\0')
- (void) strcat(fbuf, " ");
- (void) strcat(fbuf, ip->string);
- }
- /*
- * if there's anything, assign it as initials
- */
- if (strlen(fbuf) > 0)
- IVSASSIGN('n', fbuf);
- }
- /*
- * initials not yet known -- fill them in
- */
- if (!fi){
- /*
- * load into temp buffer one name at a time, in lower case
- */
- f = fbuf;
- ip = findiv('f');
- if (ip->string != CH_NULL && ip->string[0] != '\0')
- *f++ = lowcase(ip->string[0]);
- ip = findiv('m');
- if (ip->string != CH_NULL && ip->string[0] != '\0')
- *f++ = lowcase(ip->string[0]);
- ip = findiv('s');
- if (ip->string != CH_NULL && ip->string[0] != '\0')
- *f++ = lowcase(ip->string[0]);
- *f = '\0';
- /*
- * if there's anything, assign it as initials
- */
- if (strlen(fbuf) > 0)
- IVSASSIGN('i', fbuf);
- }
-
- /*
- * if debugging print out some goodies
- */
- for(i = 0; iv[i].name != '\0'; i++){
- if (iv[i].userset)
- LOG3(LG_DEBUG, "variable %c: \"%s\",\"%s\"",
- iv[i].name, iv[i].string, iv[i].length);
- }
- return(0);
- }
-
- /*
- * set a variable
- */
- setvar(buf)
- char *buf; /* line buffer */
- {
- char keychar; /* what to set */
- char closechar; /* how to end value string */
- char valbuf[BUFSIZ]; /* value */
-
- /*
- * eat leading spaces; if nothing, done!
- */
- while(isspace(*buf))
- buf++;
- if (!*buf)
- return;
- /*
- * it's the key character
- */
- keychar = *buf++;
-
- /*
- * move to next nonblank
- */
- while(isspace(*buf))
- buf++;
-
- /*
- * now act on it
- */
- switch(*buf++){
- case '"': /* string */
- closechar = '"';
- break;
- case '[': /* file name */
- closechar = ']';
- break;
- case '{': /* program name */
- closechar = '}';
- break;
- default: /* something else (bad) */
- LOG2(LG_SYNTAX,
- "bad SETVAR specification at line %d (\"%s\")",
- linect, &buf[-1]);
- return;
- }
-
- /*
- * copy the value into the buffer
- * if not terminated properly, error
- */
- if (*(buf = getcstring(buf, valbuf, closechar)) != closechar){
- LOG2(LG_SYNTAX,
- "missing %c in SETVAR specification on line %d",
- closechar, linect);
- return;
- }
-
- /*
- * if it's a program or a file, grab the first line
- */
- if (closechar == ']' &&
- firstline(valbuf, valbuf, BUFSIZ, fopen, fclose) == 0)
- return;
- else if (closechar == '}' &&
- firstline(valbuf, valbuf, BUFSIZ, popen, pclose) == 0)
- return;
-
- /*
- * now set the sucker
- */
- if (!findiv(keychar)->userset){
- LOG2(LG_SYNTAX,
- "bad SETVAR specification at line %d (\"%s\")",
- linect, &buf[-1]);
- }
- else{
- IVSASSIGN(keychar, valbuf);
- }
- }
-
- /*
- * load the logging level
- */
- loadlevel(line)
- char *line;
- {
- beginlog(line);
- }
-
- /*
- * returns a pointer to an internal variable
- */
- struct intvar *findiv(c)
- char c; /* internal variable name */
- {
- register struct intvar *ip; /* pointer to internal variable */
-
- for(ip = &iv[0]; ip->name != '\0'; ip++)
- if (ip->name == c)
- return(ip);
- return(IV_NULL);
- }
-